#ifndef __THREAD_POOL_HPP__
#define __THREAD_POOL_HPP__

#include <iostream>
#include <queue>
#include <vector>
#include "Thread.hpp"
#include "LockGuard.hpp"
#include "Task.hpp"

const int g_thread_num=5;

template<class T>
class ThreadPool
{
private:
    bool isEmpty()
    {
        return _task_queue.empty();
    }

    pthread_mutex_t* getMutex()
    {
        return &_mtx;
    }

    void waitCond()
    {
        pthread_cond_wait(&_cond,&_mtx);
    }

    Task getTask()
    {
        Task t=_task_queue.front();
        _task_queue.pop();
        return t;
    }

private:
    ThreadPool(int num=g_thread_num)
        :_num(num)
    {
        pthread_mutex_init(&_mtx,nullptr);
        pthread_cond_init(&_cond,nullptr);

        for(int i=0;i<_num;i++)
        {
            _threads.push_back(new Thread(i,routine,this));
        }
    }

    ThreadPool(const ThreadPool<T>&)=delete;
    const ThreadPool<T>& operator=(const ThreadPool<T>&)=delete;
public:
    static ThreadPool<T>* getThreadPool(int num=g_thread_num)
    {
        if(_thread_ptr==nullptr)
        {
            LockGuard lg(&_thread_mutex);
            if(_thread_ptr==nullptr)
            {
                _thread_ptr=new ThreadPool<T>(num);
            }
        }
        return _thread_ptr;
    }

    static void* routine(void* args)
    {
        ThreadData* td=(ThreadData*)args;
        ThreadPool<T>* tp=(ThreadPool<T>*)td->args;
        while(true)
        {
            //处理逻辑
            Task task;
            {
                LockGuard lg(tp->getMutex());
                while(tp->isEmpty())
                {
                    tp->waitCond();
                }

                task=tp->getTask();
            }

            task(td->_name);
        }
    }

    void run()
    {
        for(auto& iter:_threads)
        {
            iter->create();
        }
    }

    void push(const T& in)
    {
        LockGuard lg(&_mtx);
        _task_queue.push(in);
        pthread_cond_signal(&_cond);
    }

    ~ThreadPool()
    {
        for(auto& iter:_threads)
        {
            iter->join();
            delete iter;
        }

        delete _thread_ptr;
    }
    
private:
    std::vector<Thread*> _threads;//线程池
    std::queue<T> _task_queue;//阻塞队列
    int _num;//记录线程池中线程数
    pthread_mutex_t _mtx;//锁
    pthread_cond_t _cond;//条件变量

    static ThreadPool<T>* _thread_ptr;//单例
    static pthread_mutex_t _thread_mutex;//单例要用的锁
};
template<class T>
ThreadPool<T>* ThreadPool<T>::_thread_ptr=nullptr;
template<class T>
pthread_mutex_t ThreadPool<T>::_thread_mutex=PTHREAD_MUTEX_INITIALIZER;

#endif